﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Reflection;
using Missbot.Common;
using Missbot.Core.Base;
using Missbot.Core.Cache;

namespace Missbot.AIModule.Base
{
    /// <summary>
    /// 入口单元
    /// </summary>
    public class ModEnterUnit
    {
        /// <summary>
        /// 包含的方法
        /// </summary>
        public MethodInfo Method { get; init; }

        /// <summary>
        /// 入口特性
        /// </summary>
        public ModuleEnterAttribute Attr { get; init; }

        /// <summary>
        /// 调用模块
        /// </summary>
        public IAIModule SenderModule { get; init; }

        /// <summary>
        /// 方法参数列表
        /// </summary>
        public ParameterInfo[] Params { get; init; }

        #region Svcs

        private static DailyLimitSvc DailyLimitSvc => AutofacSvc.Resolve<DailyLimitSvc>();
        private static ILogSvc ILogSvc => AutofacSvc.Resolve<ILogSvc>();
        private static CmdLockerSvc CmdLockerSvc => AutofacSvc.Resolve<CmdLockerSvc>();

        #endregion

        /// <summary>
        /// 执行方法
        /// </summary>
        /// <param name="params"></param>
        /// <param name="session"></param>
        public void Invoke(IEnumerable<object> @params, InboxSession session)
        {
            if (!CheckAuth(Attr, session))
            {
                session.SendBack($"权限不足，此命令需要 【{Attr.AuthLvl}】 权限");
                return;
            }

            if (!DailyLimitSvc.Check(session.User.ID, Attr.ID, Attr.DailyLimit))
            {
                session.SendBack($"你今天 【{Attr.Command}】 的次数已用完");
                return;
            }

            var cmdLock = Attr.ID;
            if (!CmdLockerSvc.TryLock(session.User.ID, cmdLock, TimeSpan.FromMinutes(10)))
            {
                return;
            }

            var result = false;
            try
            {
                result = (bool?)Method.Invoke(SenderModule, new object[]{session}.Concat(@params).ToArray()) ?? false;
            }
            catch (Exception e)
            {
                ILogSvc.LogError(e);
            }
            finally
            {
                if (!string.IsNullOrEmpty(cmdLock))
                {
                    CmdLockerSvc.ReleaseLock(session.User.ID, cmdLock);
                }
            }

            // 如果操作成功，则要扣除每日次数
            if (result)
            {
                DailyLimitSvc.Cache(session.User.ID, Attr.ID);
            }
        }

        /// <summary>
        /// 权限检查
        /// </summary>
        /// <param name="attr"></param>
        /// <param name="session"></param>
        /// <returns></returns>
        private bool CheckAuth(ModuleEnterAttribute attr, InboxSession session)
        {
            var msgAuth = GetMsgAuth(session);

            return (int)msgAuth >= (int)attr.AuthLvl;
        }

        /// <summary>
        /// 获取消息权限等级
        /// </summary>
        /// <param name="session"></param>
        /// <returns></returns>
        private AuthorityLevel GetMsgAuth(InboxSession session)
        {
            if (session.User.ID == Configger<AIConfigBase>.AIConfig.Instance.DeveloperID)
            {
                return AuthorityLevel.Developer;
            }

            if (session.Group == null || session.User.ID != session.Group.OwnerID)
            {
                return AuthorityLevel.Member;
            }

            return AuthorityLevel.Owner;
        }
    }
}